/*
 * Copyright 2011 The Rusted Roof, LLC.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.proteusframework.platformservice.persistence.basic;

import org.proteusframework.core.util.Assert;
import org.proteusframework.platformservice.persistence.api.IVFSFile;
import org.proteusframework.platformservice.persistence.api.IVFSVisitor;
import org.proteusframework.platformservice.persistence.base.AbstractVFSManager;
import org.proteusframework.platformservice.persistence.vfs.FilePath;
import org.proteusframework.platformservice.persistence.vfs.VFSFile;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

public class DefaultVFSManager extends AbstractVFSManager
{
    private static final Logger logger = Logger.getLogger(DefaultVFSManager.class.getCanonicalName());

    private File currentProjectVFSRoot;

    void initializeVirtualFileSystem(File currentProjectRoot)
    {
        currentProjectVFSRoot = new File(currentProjectRoot, "vfs");
        currentProjectVFSRoot.mkdirs();
        logger.config("Project VFS mapped to " + currentProjectVFSRoot.getAbsolutePath());
    }

    @Override
    public boolean supportsVFSManagement()
    {
        return true;
    }

    @Override
    public boolean hasFile(FilePath filePath)
    {
        Assert.parameterNotNull(filePath, "Parameter 'filePath' must not be null");

        if (!getProjectManager().isProjectOpen())
        {
            throw new IllegalStateException("No project is currently open, therefore there is no active virtual file system");
        }

        File f = new File(currentProjectVFSRoot, filePath.toString());
        return f.exists();
    }

    @Override
    public List<IVFSFile> getFiles(FilePath filePath)
    {
        Assert.parameterNotNull(filePath, "Parameter 'filePath' must not be null");

        if (!getProjectManager().isProjectOpen())
        {
            throw new IllegalStateException("No project is currently open, therefore there is no active virtual file system");
        }

        List<IVFSFile> fileList = new ArrayList<IVFSFile>();

        File f = new File(currentProjectVFSRoot, filePath.toString());

        int stripLength = currentProjectVFSRoot.getAbsolutePath().length();

        File[] files = f.listFiles();
        for (File file : files)
        {
            FilePath vfsFilePath = new FilePath(file.getAbsolutePath().substring(stripLength));

            // Strip off the leading path of the vfs root
            IVFSFile vfsFile = new VFSFile(vfsFilePath.getParent().toString(),
                    vfsFilePath.getName(),
                    currentProjectVFSRoot,
                    vfsFilePath);

            fileList.add(vfsFile);
        }

        return fileList;
    }

    @Override
    public IVFSFile getFile(FilePath filePath)
    {
        Assert.parameterNotNull(filePath, "Parameter 'filePath' must not be null");

        if (!getProjectManager().isProjectOpen())
        {
            throw new IllegalStateException("No project is currently open, therefore there is no active virtual file system");
        }

        File f = new File(currentProjectVFSRoot, filePath.toString());

        int stripLength = currentProjectVFSRoot.getAbsolutePath().length();

        FilePath vfsFilePath = new FilePath(f.getAbsolutePath().substring(stripLength));

        // Strip off the leading path of the vfs root
        return new VFSFile(vfsFilePath.getParent().toString(),
                vfsFilePath.getName(),
                currentProjectVFSRoot,
                vfsFilePath);
    }

    @Override
    public IVFSFile createFile(FilePath filePath)
    {
        Assert.parameterNotNull(filePath, "Parameter 'filePath' must not be null");

        if (!getProjectManager().isProjectOpen())
        {
            throw new IllegalStateException("No project is currently open, therefore there is no active virtual file system");
        }

        File parentDir = new File(currentProjectVFSRoot, filePath.getParent().toString());
        parentDir.mkdirs();

        File f = new File(currentProjectVFSRoot, filePath.toString());

        int stripLength = currentProjectVFSRoot.getAbsolutePath().length();

        FilePath vfsFilePath = new FilePath(f.getAbsolutePath().substring(stripLength));

        // Strip off the leading path of the vfs root

        return new VFSFile(vfsFilePath.getParent().toString(),
                vfsFilePath.getName(),
                currentProjectVFSRoot,
                vfsFilePath);
    }

    @Override
    public boolean deleteFile(IVFSFile vfsFile)
    {
        Assert.parameterNotNull(vfsFile, "Parameter 'vfsFile' must not be null");
        return deleteFile(vfsFile.getFilePath());
    }

    @Override
    public boolean deleteFile(FilePath filePath)
    {
        Assert.parameterNotNull(filePath, "Parameter 'filePath' must not be null");

        if (!getProjectManager().isProjectOpen())
        {
            throw new IllegalStateException("No project is currently open, therefore there is no active virtual file system");
        }

        File f = new File(currentProjectVFSRoot, filePath.toString());
        return f.delete();
    }

    @Override
    public void accept(IVFSVisitor visitor) throws IOException
    {
        if (getProjectManager().isProjectOpen())
        {
            visitor.visit(this);
        } else
        {
            throw new IllegalStateException("Unable to accept IVFSVisitor as no project is presently open");
        }
    }
}
